# To change this template, choose Tools | Templates
# and open the template in the editor.

class Bench
  #funzione logaritmica base 2 per il calcolo del Discounted Cumulative Gain
  def log2( x )
    Math.log( x ) / Math.log( 2 )
  end
  def sqr ( n )
    n * n
  end
  def mda(width,height)
    a = Array.new(width)
    a.map! { Array.new(height) }
    return a
  end

  # metodo di benchmark che unisce i vari confronti a coppie in un unico vettore
  def benchmark(utenti)
    results = []
    for i in (0..utenti.size-1)
      results.push(benchmark_coppia_ndcg(utenti[i].context_1,utenti[i].predict(utenti, 0.9)))
    end
    return results
  end
  # confronto a coppie: prevista / originale, con calcolo del nDCG
  def benchmark_coppia_ndcg(u,up)
    dcg = up[0].to_f
    idcg = u[0].to_f
    for i in (1..up.size-1)
      dcg = dcg + (up[i].to_f / log2(i+1))
    end
    for i in (1..u.size-1)
      idcg = idcg + (u[i].to_f / log2(i+1))
    end
    return dcg/idcg
  end
  #metodo mean absolute error
  def benchmark_coppia_mae(u,up)
    somma = 0
    for i in (0..u.size-1)
      somma = somma + (up[i].to_f - u[i].to_f).abs
    end
    return somma/u.size
  end
  #metodo root mean square deviation o error
  def benchmark_coppia_rmse(u,up)
    somma = 0
    for i in (0..u.size-1)
      somma = somma + sqr(up[i].to_f - u[i].to_f)
    end
    somma = somma/u.size
    return Math.sqrt(somma)
  end
  #metodo NORMALIZED root mean square deviation o error
  def benchmark_coppia_nrmse(u,up)
    rmse = benchmark_coppia_rmse(u,up)
    u = u.sort
    diff = 1
    if (u[u.size-1] - u[0]) != 0
      diff = (u[u.size-1] - u[0])
    end
    return rmse / diff
  end
  #metodo R-square
  def benchmark_coppia_Rsquare(u,up)
    somma = 0
    sstot = 0
    sserr = 0
    for i in (0..u.size-1)
      somma = somma + u[i].to_f
    end
    ymed = somma / u.size
    for i in (0..u.size-1)
      sstot = sstot + (u[i].to_f - ymed)**2
    end
    for i in (0..u.size-1)
      sserr = sserr + (u[i].to_f - up[i].to_f)**2
    end
    return 1 - (sserr / sstot)
  end
  #metodo Hit-Rate
  def benchmark_coppia_hitrate(u,up)
    hit = 0
    fail = 0
    for i in (0..u.size-1)
      if u[i] == up[i]
        hit += 1
      else
        fail += 1
      end
    end
    return hit.to_f / (hit + fail)
  end
  #Metodo Chi-Square
  def benchmark_coppia_chisquare(u,up)
    #definizione tabella
    t = mda(3,u.size+1)
    #ciclo azzeramento tabella
    for i in (0..t.size-1)
      for j in (0..t[0].size-1)
        t[i][j] = 0
      end
    end
    #assegnazione valori riga 1 e somma totale riga
    for i in (0..u.size-1)
      t[0][i] = u[i].to_f
      t[0][t[0].size-1] += t[0][i]
    end
    #assegnazione valori riga 2 e somma totale riga
    for i in (0..up.size-1)
      t[1][i] = up[i].to_f
      t[1][t[0].size-1] += t[1][i]
    end
    #somma delle colonne
    for i in (0..t[0].size-2)
      t[2][i] = t[0][i] + t[1][i]
    end
    #grantotale della somma colonne
    for i in (0..t[0].size-2)
      t[t.size-1][t[0].size-1] += t[2][i]
    end
    #verifica di correttezza tabella di contingenza
    if t[t.size-1][t[0].size-1] == t[0][t[0].size-1]+t[1][t[0].size-1]
      #definizione matrice delle frequenze stimate
      e = mda(t.size-1,t[0].size-1)
      for i in (0..e.size-1) #righe
        for j in (0..e[0].size-1) #colonne
          e[i][j] = (t[i][t[0].size-1]*t[t.size-1][j])/t[t.size-1][t[0].size-1]
        end
      end
      chisquare = 0
      for i in (0..e.size-1)
        for j in (0..e[0].size-1)
          chisquare += sqr(t[i][j] - e[i][j]) / e[i][j]
        end
      end
    end
    return chisquare
    #,((e.size-1)*(e[0].size-1))
  end
end
